package gwt.templates.example.client;

import gwt.templates.FieldInfo;
import gwt.templates.FieldInfoFactoryRegistry;
import gwt.templates.IFieldInfoFactory;
import gwt.templates.IFieldInfoVIsitor;
import gwt.templates.ITemplateNamespaces;
import gwt.templates.TemplatePanelBuilder;
import gwt.templates.TemplateTopPanel;
import gwt.templates.ioutil.TemplateLoader;

import java.util.Map;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class TemplateExample implements EntryPoint {

    abstract static class Callback<T> implements AsyncCallback<T> {
        /**
         * @see com.google.gwt.user.client.rpc.AsyncCallback#onFailure(java.lang.Throwable)
         */
        public void onFailure(Throwable caught) {
            throw new RuntimeException(caught);
            // Window.alert("ERROR: " + caught.getMessage());
        }
    }

    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {
        final Button button = new Button("Click me");
        final FlowPanel internalPanel = new FlowPanel();

        final FieldInfoFactoryRegistry registry = new FieldInfoFactoryRegistry();
        registry.addFieldInfoFactoryNS(
            ITemplateNamespaces.NS_TEMPLATES,
            "titi",
            new IFieldInfoFactory() {

                public FieldInfo<?> newFieldInfo(
                    TemplateTopPanel context,
                    Map<String, String> attributes) {
                    return new FieldInfo<HTML>(context, attributes) {

                        private String fValue;

                        @Override
                        public void clear() {
                            setValue(getWidget(), "XXX");
                        }

                        @Override
                        public Object getValue() {
                            return fValue;
                        }

                        @Override
                        protected HTML newWidget() {
                            HTML widget = new HTML();
                            setValue(widget, null);
                            return widget;
                        }

                        /**
                         * @param widget
                         * @param value
                         */
                        private void setValue(HTML widget, Object value) {
                            fValue = value != null
                                ? value.toString()
                                : getLabelFromAttributes();
                            widget.setHTML("<h1>" + fValue + "</h1>");
                        }

                        @Override
                        public boolean setValue(Object value) {
                            HTML widget = this.getWidget();
                            setValue(widget, value);
                            return true;
                        }

                    };
                }
            });

        button.addClickListener(new ClickListener() {
            public void onClick(Widget sender) {
                TemplatePanelBuilder builder = new TemplatePanelBuilder(
                    registry);
                TemplateLoader loader = new TemplateLoader(builder);
                loader.load(
                    "TemplateExample-template.i18n",
                    "TemplateExample-template.xml",
                    new Callback<TemplatePanelBuilder>() {
                        public void onSuccess(TemplatePanelBuilder result) {
                            showTemplatePanel(internalPanel, result);
                        }
                    });
            }
        });
        FlowPanel panel = new FlowPanel();
        panel.add(button);
        panel.add(internalPanel);
        RootPanel.get().add(panel);
    }

    /**
     * @param internalPanel
     * @param result
     */
    private void showTemplatePanel(
        final FlowPanel internalPanel,
        TemplatePanelBuilder result) {
        final TemplateTopPanel panel = result.buildPanel("mainPanel");
        panel.addSubmitListener(new ClickListener() {
            public void onClick(Widget sender) {
                panel.setEnabled(false);
                final StringBuffer buf = new StringBuffer();
                panel.accept(new IFieldInfoVIsitor() {
                    public void visit(FieldInfo<?> info) {
                        Object value = info.getValue();
                        if (value != null) {
                            buf.append(info.getName());
                            buf.append("=");
                            buf.append(value);
                            buf.append("\n");
                        }
                    }
                });
                String str = buf.toString();
                Window.alert(str);
                panel.setEnabled(true);
            }
        });
        panel.addCancelListener(new ClickListener() {
            public void onClick(Widget sender) {
                panel.setEnabled(false);
                Window.alert("Cancelled...");
                panel.setEnabled(true);
            }
        });
        internalPanel.clear();
        internalPanel.add(panel);
    }

}
